package com.sz.biz.logistics.base.service.impl;

import com.sz.biz.common.constants.ErrorCodes;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.logistics.base.dto.ShippingLineDetailDto;
import com.sz.biz.logistics.base.dto.ShippingLineDto;
import com.sz.biz.logistics.base.dto.ShippingLineSettingDetailDto;
import com.sz.biz.logistics.base.dto.ShippingLineSettingDto;
import com.sz.biz.logistics.base.entity.Ship;
import com.sz.biz.logistics.base.entity.ShippingCompany;
import com.sz.biz.logistics.base.entity.ShippingLineSetting;
import com.sz.biz.logistics.base.entity.ShippingLineSettingDetail;
import com.sz.biz.logistics.base.service.*;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.DaoSupport;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.dto.ResultDto;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.service.AbstractService;
import com.sz.common.base.utils.CollectionUtils;
import com.sz.common.base.utils.DateUtils;
import com.sz.common.base.utils.EntityUtils;
import com.sz.common.base.utils.StringUtils;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.*;

/**
 * Function: 轮班shippingLineSettingService <br>
 * Author: wentao.chang <br>
 * Date: 2017-08-04 15:41:00
 */
@Service("shippingLineSettingService")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class ShippingLineSettingServiceImpl extends AbstractService implements ShippingLineSettingService {

    @Resource(name = "daoSupport")
    private DaoSupport dao;

    @Autowired
    private ShippingLineService shippingLineService;

    @Autowired
    private ShippingCompanyService shippingCompanyService;

    @Autowired
    private ShipService shipService;

    @Autowired
    private ShippingLineSettingDetailService shippingLineSettingDetailService;

    @Override
    public int save(ShippingLineSettingDto shippingLineSettingDto) {
        List<ShippingLineSettingDetailDto> detailDtos =  shippingLineSettingDto.getPorts();
        this.judgeParam(detailDtos);

        ShippingLineSetting shippingLineSetting = new ShippingLineSetting();
        EntityUtils.copyPropertiesIgnoreNull(shippingLineSettingDto, shippingLineSetting);
        // 检查数据不能重复
        checkCode(shippingLineSetting.getCode(), null);
        shippingLineSetting.setCreateUserId(PrincipalUtils.getAccountId());
        shippingLineSetting.setLastUpdateUserId(PrincipalUtils.getAccountId());
        dao.save("ShippingLineSettingMapper.insert", shippingLineSetting);
        saveDetail(shippingLineSetting.getId(), shippingLineSettingDto);
        // 保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_SHIPPINGLINESETTING", shippingLineSetting);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SHIPPINGLINESETTING, UserActions.ADD, "新建海运航班",
                dataBackup);
        return shippingLineSetting.getId();
    }

    private void judgeParam(List<ShippingLineSettingDetailDto> detailDtos) {
        if(!CollectionUtils.isEmpty(detailDtos)){
            if(ObjectUtils.isEmpty(detailDtos.get(0).getEtdStr())){//第一个的离港日期
                throw Exceptions.bizException(ErrorCodes.ERROR_COMMON,"第一个离港日期不能为空！");
            }
            if(ObjectUtils.isEmpty(detailDtos.get(detailDtos.size()-1).getEtaStr())){//最后一个的到港日期
                throw Exceptions.bizException(ErrorCodes.ERROR_COMMON,"最后一个到港日期不能为空！");
            }
        }
    }

    private void saveDetail(Integer shippingLineSettingId, ShippingLineSettingDto shippingLineSettingDto) {
        if (!CollectionUtils.isEmpty(shippingLineSettingDto.getPorts())) {
            final Integer[] i = {1};
            shippingLineSettingDto.getPorts().forEach(item -> {
                try {
                    item.setEta(DateUtils.parseDate(item.getEtaStr(),DateUtils.FORMAT_SIMPLE));
                    item.setEtd(DateUtils.parseDate(item.getEtdStr(),DateUtils.FORMAT_SIMPLE));
                    item.setCargoDeadTime(DateUtils.parseDate(item.getCargoDeadTimeStr(),DateUtils.FORMAT_SIMPLE));
                    item.setPortDeadTime(DateUtils.parseDate(item.getPortDeadTimeStr(),DateUtils.FORMAT_SIMPLE));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                item.setShippingLineSettingId(shippingLineSettingId);
                item.setOrdinal(i[0]++);
            });
            shippingLineSettingDetailService.save(shippingLineSettingDto.getPorts());
        }
    }

    @Override
    public int update(Integer id, ShippingLineSettingDto shippingLineSettingDto) {
        List<ShippingLineSettingDetailDto> detailDtos =  shippingLineSettingDto.getPorts();
        this.judgeParam(detailDtos);

        ShippingLineSetting shippingLineSettingExist = findSimpleById(id);
        if (shippingLineSettingExist.getIsDeleted()) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_HAS_DELETED, id);
        }
        ShippingLineSetting shippingLineSetting = new ShippingLineSetting();
        EntityUtils.copyPropertiesIgnoreNull(shippingLineSettingDto, shippingLineSetting);
        // 检查数据不能重复
        checkCode(shippingLineSetting.getCode(), id);
        shippingLineSetting.setLastUpdateUserId(PrincipalUtils.getAccountId());
        shippingLineSetting.setId(id);
        dao.update("ShippingLineSettingMapper.update", shippingLineSetting);
        shippingLineSettingDetailService.deleteByShippingLineSettingId(id);
        saveDetail(id, shippingLineSettingDto);

        // 保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_SHIPPINGLINESETTING", shippingLineSetting);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SHIPPINGLINESETTING, UserActions.UPDATE, "修改海运航班",
                dataBackup);
        return id;
    }

    @Override
    public void checkCode(String code, Integer id) {
        if (StringUtils.isEmpty(code)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "code");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("code", code);
        map.put("id", id);
        ShippingLineSetting shipExist = (ShippingLineSetting) dao.findForObject("ShippingLineSettingMapper.checkCode", map);
        if (shipExist != null) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_CODE_EXIST, ModuleNames.BIZ_SHIPPINGLINESETTING);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteByIds(List<Integer> ids) {
        dao.update("ShippingLineSettingMapper.deleteByIds", ids);
        // 保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("DELETE_SHIPPINGLINESETTING", ids);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SHIPPINGLINESETTING, UserActions.DELETE, "删除海运航班",
                dataBackup);

    }

    @Override
    public ShippingLineSettingDto findById(int id) {
        ParamData pd = new ParamData();
        pd.put("id", id);
        ShippingLineSetting shippingLineSetting = (ShippingLineSetting) dao.findForObject("ShippingLineSettingMapper.findById", pd);
        ShippingLineSettingDto shippingLineSettingDto = new ShippingLineSettingDto();
        if (shippingLineSetting == null) {
            return shippingLineSettingDto;
        }
        BeanUtils.copyProperties(shippingLineSetting, shippingLineSettingDto);
        if (shippingLineSetting.getShipId() != null) {
            Ship ship = shipService.findSimpleById(shippingLineSetting.getShipId());
            if(ship!=null){

                shippingLineSettingDto.setShipName(ship.getName());
                shippingLineSettingDto.setShipEnglishName(ship.getNameEn());
            }
        }

        if (shippingLineSetting.getShippingCompanyId() != null) {
            List<ShippingCompany> ccs = shippingCompanyService.findByIds(Collections.singletonList(shippingLineSetting.getShippingCompanyId()));
            Map<String, ShippingCompany> ccMap = EntityUtils.getStringKeyMapFromBeans(ccs, "id");
            if (ccMap.get(shippingLineSetting.getShippingCompanyId() + "") != null) {
                shippingLineSettingDto.setShippingCompanyName(ccMap.get(shippingLineSetting.getShippingCompanyId() + "").getName());
            }
        }
        getShippingLineName(shippingLineSetting.getShippingLineId(), shippingLineSettingDto);

        return shippingLineSettingDto;
    }

    private void getShippingLineName(Integer shippingLineId, ShippingLineSettingDto shippingLineSettingDto) {
        if (shippingLineId != null) {
            ShippingLineDto airline = shippingLineService.findById(shippingLineId);
            shippingLineSettingDto.setShippingLineName(airline.getName());

            List<ShippingLineSettingDetail> details = shippingLineSettingDetailService.findByShippingLineSettingId(shippingLineSettingDto.getId());
            if (!CollectionUtils.isEmpty(details)) {
                List<ShippingLineDetailDto> ports = airline.getPorts();
                Map<String, ShippingLineDetailDto> portsmap = EntityUtils.getStringKeyMapFromBeans(ports, "portId");
                details.forEach(detail -> {

                    ShippingLineSettingDetailDto detailDto = new ShippingLineSettingDetailDto();
                    BeanUtils.copyProperties(detail, detailDto);
                    if (portsmap.get(detail.getPortId() + "") != null) {
                        detailDto.setPortName(portsmap.get(detail.getPortId() + "").getPortName());
                        detailDto.setPortEnglishName(portsmap.get(detail.getPortId()+"").getPortEnglishName());
                    }
                    detailDto.setEtaStr(DateUtils.formatSimpleDate(detailDto.getEta()));
                    detailDto.setEtdStr(DateUtils.formatSimpleDate(detailDto.getEtd()));
                    detailDto.setCargoDeadTimeStr(DateUtils.formatSimpleDate(detailDto.getCargoDeadTime()));
                    detailDto.setPortDeadTimeStr(DateUtils.formatSimpleDate(detailDto.getPortDeadTime()));
                    shippingLineSettingDto.getPorts().add(detailDto);
                });
            }
            if (!CollectionUtils.isEmpty(details)) {
                ShippingLineSettingDetailDto first = shippingLineSettingDto.getPorts().get(0);
                ShippingLineSettingDetailDto last = shippingLineSettingDto.getPorts().get(details.size() - 1);
                shippingLineSettingDto.setEta(last.getEta());
                shippingLineSettingDto.setEtd(first.getEtd());
                shippingLineSettingDto.setEtaStr(DateUtils.formatSimpleDate(last.getEta()));
                shippingLineSettingDto.setEtdStr(DateUtils.formatSimpleDate(first.getEtd()));

                shippingLineSettingDto.setStartName(first.getPortName());
                shippingLineSettingDto.setStartEnglishName(first.getPortEnglishName());
                shippingLineSettingDto.setEndName(last.getPortName());
                shippingLineSettingDto.setEndEnglishName(last.getPortEnglishName());
                if (last.getEta() != null && first.getEtd() != null) {
                    long diff = last.getEta().getTime() - first.getEtd().getTime();
                    int diffint = Integer.parseInt(diff/1000 + "");
                    shippingLineSettingDto.setDays(diffint / (24 * 60 * 60 ));
                }
            }


        }
    }


    @Override
    public ResultDto findShippingLineSettingListPage(QueryParams params) {
        ParamData pd = this.convertQueryParams(params);
        // 调用方法查询数据
        List<ShippingLineSetting> list = dao.findForList("ShippingLineSettingMapper.shippingLineSettingListPage", pd, ShippingLineSetting.class);
        List<ShippingLineSettingDto> dtos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {

            list.forEach(shippingLineSetting -> {
                ShippingLineSettingDto dto = new ShippingLineSettingDto();
                BeanUtils.copyProperties(shippingLineSetting, dto);

                if (shippingLineSetting.getShipId() != null) {
                    Ship ship = shipService.findSimpleById(shippingLineSetting.getShipId());
                    if(ship!=null){
                        dto.setShipName(ship.getName());
                        dto.setShipEnglishName(ship.getNameEn());
                        if (ship.getCompanyId() != null) {
                            ShippingCompany sc = shippingCompanyService.findSimpleById(ship.getCompanyId());
                            if (sc != null) {
                                dto.setShippingCompanyName(sc.getName());
                            }
                        }
                    }
                }
                getShippingLineName(shippingLineSetting.getShippingLineId(), dto);
                dtos.add(dto);
            });
        }
        QResultDto dto = new QResultDto();
        dto.setData(dtos);
        dto.setPagination(pd.getPagination());
        return dto;
    }

    /**
     * 根据shipId查询海运航班信息
     *
     * @param id id
     * @return ShippingLineSetting
     */
    @Override
    public ShippingLineSetting findSimpleById(int id) {
        return (ShippingLineSetting) dao.findForObject("ShippingLineSettingMapper.findById", id);
    }

    /**
     * 根据shipIds查询海运航班信息
     *
     * @param ids ids
     * @return ShippingLineSetting
     */
    @Override
    public List<ShippingLineSetting> findSimpleByIds(List<Integer> ids) {
        return dao.findForList("ShippingLineSettingMapper.findByIds", ids, ShippingLineSetting.class);
    }

    /**
     * 根据条件分页查询海运航班短接口
     *
     * @param params params
     * @return ResultDto
     */
    @Override
    public ResultDto findShippingLineSettingShortListPage(QueryParams params) {
        ParamData pd = this.convertQueryParams(params);
        // 调用方法查询数据
        List<ShippingLineSetting> list = dao.findForList("ShippingLineSettingMapper.shippingLineSettingShortListPage", pd, ShippingLineSetting.class);
        QResultDto dto = new QResultDto();
        dto.setData(list);
        dto.setPagination(pd.getPagination());
        return dto;
    }


    @Override
    protected String getMapperNamespace() {
        return "ShippingLineSettingMapper";
    }
}
